using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using PickGold.Charting;
using System.Xml;

namespace PickGold.Charting.Utilities
{
    internal abstract class SerializerBase
    {
        private HybridDictionary _converterDict = new HybridDictionary();
        private bool _isResetWhenLoading = true;
        private bool _isTemplateMode;
        private bool _isUnknownAttributeIgnored;
        private string _nonSerializableContent = "";
        private string _serializableContent = "";
        internal static ColorConverter colorConverter = new ColorConverter();
        internal static FontConverter fontConverter = new FontConverter();
        protected static StringComparer hashCodeProvider = StringComparer.OrdinalIgnoreCase;
        private ArrayList nonSerializableContentList;
        private ArrayList serializableContentList;

        protected SerializerBase()
        {
        }

        private void CheckWildCars(ItemInfo info)
        {
            if (info.name == "*")
            {
                info.any = true;
            }
            else if (info.name[info.name.Length - 1] == '*')
            {
                info.endsWith = true;
                info.name = info.name.TrimEnd(new char[] { '*' });
            }
            else if (info.name[0] == '*')
            {
                info.startsWith = true;
                info.name = info.name.TrimStart(new char[] { '*' });
            }
        }

        internal abstract void Deserialize(object objectToDeserialize, object source);
        private void FillContentList(ArrayList list, string content)
        {
            if (content.Length > 0)
            {
                foreach (string str in content.Split(new char[] { ',' }))
                {
                    ItemInfo info = new ItemInfo();
                    ItemInfo info2 = new ItemInfo();
                    int index = str.IndexOf('.');
                    if (index == -1)
                    {
                        throw new ArgumentException(SR.ExceptionChartSerializerContentStringFormatInvalid);
                    }
                    info.name = str.Substring(0, index).Trim();
                    info2.name = str.Substring(index + 1).Trim();
                    if (info.name.Length == 0)
                    {
                        throw new ArgumentException(SR.ExceptionChartSerializerClassNameUndefined);
                    }
                    if (info2.name.Length == 0)
                    {
                        throw new ArgumentException(SR.ExceptionChartSerializerPropertyNameUndefined);
                    }
                    if (info2.name.IndexOf('.') != -1)
                    {
                        throw new ArgumentException(SR.ExceptionChartSerializerContentStringFormatInvalid);
                    }
                    this.CheckWildCars(info);
                    this.CheckWildCars(info2);
                    list.Add(info);
                    list.Add(info2);
                }
            }
        }

        internal TypeConverter FindConverter(PropertyDescriptor pd)
        {
            TypeConverterAttribute attr = (TypeConverterAttribute) pd.Attributes[typeof(TypeConverterAttribute)];
            if ((attr != null) && (attr.ConverterTypeName.Length > 0))
            {
                TypeConverter converter = this.FindConverterByType(attr);
                if (converter != null)
                {
                    return converter;
                }
                try
                {
                    return pd.Converter;
                }
                catch (SecurityException)
                {
                }
                catch (MethodAccessException)
                {
                }
            }
            return TypeDescriptor.GetConverter(pd.PropertyType);
        }

        internal TypeConverter FindConverterByType(TypeConverterAttribute attr)
        {
            if (this._converterDict.Contains(attr.ConverterTypeName))
            {
                return (TypeConverter) this._converterDict[attr.ConverterTypeName];
            }
            string converterTypeName = attr.ConverterTypeName;
            if (attr.ConverterTypeName.Contains(","))
            {
                converterTypeName = attr.ConverterTypeName.Split(new char[] { ',' })[0];
            }
            TypeConverter converter = null;
            if (converterTypeName.EndsWith(".CustomPropertiesTypeConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new CustomPropertiesTypeConverter();
            }
            else if (converterTypeName.EndsWith(".DoubleNanValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new DoubleNanValueConverter();
            }
            else if (converterTypeName.EndsWith(".DoubleDateNanValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new DoubleDateNanValueConverter();
            }
            else if (converterTypeName.EndsWith(".MapAreaCoordinatesConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new MapAreaCoordinatesConverter();
            }
            else if (converterTypeName.EndsWith(".ElementPositionConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new ElementPositionConverter();
            }
            else if (converterTypeName.EndsWith(".SeriesAreaNameConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new SeriesAreaNameConverter();
            }
            else if (converterTypeName.EndsWith(".ChartDataSourceConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new ChartDataSourceConverter();
            }
            else if (converterTypeName.EndsWith(".SeriesDataSourceMemberConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new SeriesDataSourceMemberConverter();
            }
            else if (converterTypeName.EndsWith(".SeriesLegendNameConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new SeriesLegendNameConverter();
            }
            else if (converterTypeName.EndsWith(".ChartTypeConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new ChartTypeConverter();
            }
            else if (converterTypeName.EndsWith(".SeriesNameConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new SeriesNameConverter();
            }
            else if (converterTypeName.EndsWith(".NoNameExpandableObjectConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new NoNameExpandableObjectConverter();
            }
            else if (converterTypeName.EndsWith(".DoubleArrayConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new DoubleArrayConverter();
            }
            else if (converterTypeName.EndsWith(".DataPointValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new DataPointValueConverter();
            }
            else if (converterTypeName.EndsWith(".SeriesYValueTypeConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new SeriesYValueTypeConverter(typeof(ChartValueType));
            }
            else if (converterTypeName.EndsWith(".ColorArrayConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new ColorArrayConverter();
            }
            else if (converterTypeName.EndsWith(".LegendAreaNameConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new LegendAreaNameConverter();
            }
            else if (converterTypeName.EndsWith(".LegendConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new LegendConverter();
            }
            else if (converterTypeName.EndsWith(".SizeEmptyValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new SizeEmptyValueConverter();
            }
            else if (converterTypeName.EndsWith(".MarginExpandableObjectConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new MarginExpandableObjectConverter();
            }
            else if (converterTypeName.EndsWith(".IntNanValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new IntNanValueConverter();
            }
            else if (converterTypeName.EndsWith(".AxesArrayConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AxesArrayConverter();
            }
            else if (converterTypeName.EndsWith(".AxisLabelDateValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AxisLabelDateValueConverter();
            }
            else if (converterTypeName.EndsWith(".AxisMinMaxValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AxisMinMaxValueConverter();
            }
            else if (converterTypeName.EndsWith(".AxisCrossingValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AxisCrossingValueConverter();
            }
            else if (converterTypeName.EndsWith(".AxisMinMaxAutoValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AxisMinMaxAutoValueConverter();
            }
            else if (converterTypeName.EndsWith(".StripLineTitleAngleConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new StripLineTitleAngleConverter();
            }
            else if (converterTypeName.EndsWith(".AxisIntervalValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AxisIntervalValueConverter();
            }
            else if (converterTypeName.EndsWith(".AxisElementIntervalValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AxisElementIntervalValueConverter();
            }
            else if (converterTypeName.EndsWith(".AnchorPointValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AnchorPointValueConverter();
            }
            else if (converterTypeName.EndsWith(".AnnotationAxisValueConverter", StringComparison.OrdinalIgnoreCase))
            {
                converter = new AnnotationAxisValueConverter();
            }
            if (converter != null)
            {
                this._converterDict[attr.ConverterTypeName] = converter;
            }
            return converter;
        }

        internal static Font FontFromString(string fontString)
        {
            string text = fontString;
            byte gdiCharSet = 1;
            bool gdiVerticalFont = false;
            int index = fontString.IndexOf(", GdiCharSet=", StringComparison.Ordinal);
            if (index >= 0)
            {
                string s = fontString.Substring(index + 13);
                int length = s.IndexOf(",", StringComparison.Ordinal);
                if (length >= 0)
                {
                    s = s.Substring(0, length);
                }
                gdiCharSet = (byte) int.Parse(s, CultureInfo.InvariantCulture);
                if (text.Length > index)
                {
                    text = text.Substring(0, index);
                }
            }
            index = fontString.IndexOf(", GdiVerticalFont", StringComparison.Ordinal);
            if (index >= 0)
            {
                gdiVerticalFont = true;
                if (text.Length > index)
                {
                    text = text.Substring(0, index);
                }
            }
            Font font = (Font) fontConverter.ConvertFromInvariantString(text);
            if (!gdiVerticalFont && (gdiCharSet == 1))
            {
                return font;
            }
            Font font2 = new Font(font.Name, font.SizeInPoints, font.Style, GraphicsUnit.Point, gdiCharSet, gdiVerticalFont);
            font.Dispose();
            return font2;
        }

        internal static string FontToString(Font font)
        {
            string str = fontConverter.ConvertToInvariantString(font);
            if (font.GdiCharSet != 1)
            {
                str = str + ", GdiCharSet=" + font.GdiCharSet.ToString(CultureInfo.InvariantCulture);
            }
            if (font.GdiVerticalFont)
            {
                str = str + ", GdiVerticalFont";
            }
            return str;
        }

        internal object GetListNewItem(IList list, string itemTypeName, ref string itemName, ref bool reusedObject)
        {
            Type returnType = null;
            if (itemTypeName.Length > 0)
            {
                returnType = Type.GetType(typeof(Chart).Namespace + "." + itemTypeName, false, true);
            }
            reusedObject = false;
            PropertyInfo info = list.GetType().GetProperty("Item", returnType, new Type[] { typeof(string) });
            MethodInfo method = list.GetType().GetMethod("IndexOf", new Type[] { typeof(string) });
            ConstructorInfo constructor = null;
            if (((info != null) && (itemName != null)) && (itemName.Length > 0))
            {
                bool flag = false;
                if (method != null)
                {
                    try
                    {
                        int num = -1;
                        object obj2 = method.Invoke(list, new object[] { itemName });
                        if (obj2 is int)
                        {
                            num = (int) obj2;
                            flag = true;
                        }
                        if (num != -1)
                        {
                            object obj3 = list[num];
                            if (obj3 != null)
                            {
                                list.Remove(obj3);
                                reusedObject = true;
                                return obj3;
                            }
                        }
                    }
                    catch (ArgumentException)
                    {
                    }
                    catch (TargetException)
                    {
                    }
                    catch (TargetInvocationException)
                    {
                    }
                }
                if (!flag)
                {
                    object obj4 = null;
                    try
                    {
                        obj4 = info.GetValue(list, new object[] { itemName });
                    }
                    catch (ArgumentException)
                    {
                        obj4 = null;
                    }
                    catch (TargetException)
                    {
                        obj4 = null;
                    }
                    catch (TargetInvocationException)
                    {
                        obj4 = null;
                    }
                    if (obj4 != null)
                    {
                        try
                        {
                            list.Remove(obj4);
                        }
                        catch (NotSupportedException)
                        {
                        }
                        reusedObject = true;
                        return obj4;
                    }
                }
                itemName = null;
            }
            if (returnType != null)
            {
                constructor = returnType.GetConstructor(Type.EmptyTypes);
            }
            else
            {
                constructor = info.PropertyType.GetConstructor(Type.EmptyTypes);
            }
            if (constructor == null)
            {
                throw new InvalidOperationException(SR.ExceptionChartSerializerDefaultConstructorUndefined(info.PropertyType.ToString()));
            }
            return constructor.Invoke(null);
        }

        private ArrayList GetNonSerializableContentList()
        {
            if (this.nonSerializableContentList == null)
            {
                this.nonSerializableContentList = new ArrayList();
                this.FillContentList(this.nonSerializableContentList, this.NonSerializableContent);
            }
            return this.nonSerializableContentList;
        }

        internal string GetObjectName(object obj)
        {
            string str = obj.GetType().ToString();
            return str.Substring(str.LastIndexOf('.') + 1);
        }

        private ArrayList GetSerializableContentList()
        {
            if (this.serializableContentList == null)
            {
                this.serializableContentList = new ArrayList();
                this.FillContentList(this.serializableContentList, (this.SerializableContent.Length > 0) ? this.SerializableContent : "*.*");
            }
            return this.serializableContentList;
        }

        internal static short GetStringHashCode(string str)
        {
            return (short) (hashCodeProvider.GetHashCode(str) + (str.Length * 2));
        }

        internal static Image ImageFromString(string data)
        {
            byte[] array = new byte[0x3e8];
            MemoryStream stream = new MemoryStream();
            XmlTextReader reader = new XmlTextReader(new StringReader("<base64>" + data + "</base64>"));
            reader.Read();
            int count = 0;
            while ((count = reader.ReadBase64(array, 0, 0x3e8)) > 0)
            {
                stream.Write(array, 0, count);
            }
            reader.Read();
            stream.Seek(0L, SeekOrigin.Begin);
            Image original = Image.FromStream(stream);
            Bitmap bitmap = new Bitmap(original);
            bitmap.SetResolution(original.HorizontalResolution, original.VerticalResolution);
            reader.Close();
            stream.Close();
            return bitmap;
        }

        internal static string ImageToString(Image image)
        {
            MemoryStream stream = new MemoryStream();
            image.Save(stream, ImageFormat.Png);
            stream.Seek(0L, SeekOrigin.Begin);
            StringBuilder sb = new StringBuilder();
            XmlTextWriter writer = new XmlTextWriter(new StringWriter(sb, CultureInfo.InvariantCulture));
            byte[] buffer = stream.ToArray();
            writer.WriteBase64(buffer, 0, buffer.Length);
            writer.Close();
            stream.Close();
            return sb.ToString();
        }

        internal bool IsChartBaseProperty(object objectToSerialize, object parent, PropertyInfo pi)
        {
            if (parent == null)
            {
                for (Type type = objectToSerialize.GetType(); type != null; type = type.BaseType)
                {
                    if (pi.DeclaringType == type)
                    {
                        return false;
                    }
                    if (type == typeof(Chart))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private bool IsPropertyInList(ArrayList contentList, string className, string propertyName, out int classFitType, out int propertyFitType)
        {
            classFitType = 0;
            propertyFitType = 0;
            if (contentList != null)
            {
                for (int i = 0; i < contentList.Count; i += 2)
                {
                    classFitType = 0;
                    propertyFitType = 0;
                    if (this.NameMatchMask((ItemInfo) contentList[i], className, out classFitType) && this.NameMatchMask((ItemInfo) contentList[i + 1], propertyName, out propertyFitType))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        internal bool IsSerializableContent(string propertyName, object parent)
        {
            bool flag = true;
            if ((this._serializableContent.Length > 0) || (this._nonSerializableContent.Length > 0))
            {
                int classFitType = 0;
                int propertyFitType = 0;
                string objectName = this.GetObjectName(parent);
                flag = this.IsPropertyInList(this.GetSerializableContentList(), objectName, propertyName, out classFitType, out propertyFitType);
                if (flag)
                {
                    int num3 = 0;
                    int num4 = 0;
                    if (this.IsPropertyInList(this.GetNonSerializableContentList(), objectName, propertyName, out num3, out num4) && ((num3 + num4) > (classFitType + propertyFitType)))
                    {
                        flag = false;
                    }
                }
            }
            return flag;
        }

        private bool NameMatchMask(ItemInfo itemInfo, string objectName, out int type)
        {
            type = 0;
            if (itemInfo.any)
            {
                type = 1;
                return true;
            }
            if ((itemInfo.endsWith && (itemInfo.name.Length <= objectName.Length)) && (objectName.Substring(0, itemInfo.name.Length) == itemInfo.name))
            {
                type = 2;
                return true;
            }
            if ((itemInfo.startsWith && (itemInfo.name.Length <= objectName.Length)) && (objectName.Substring(objectName.Length - itemInfo.name.Length, itemInfo.name.Length) == itemInfo.name))
            {
                type = 2;
                return true;
            }
            if (itemInfo.name == objectName)
            {
                type = 3;
                return true;
            }
            return false;
        }

        internal short ReadHashID(BinaryReader reader)
        {
            return reader.ReadInt16();
        }

        internal virtual void ResetObjectProperties(object objectToReset)
        {
            this.ResetObjectProperties(objectToReset, null, this.GetObjectName(objectToReset));
        }

        internal virtual void ResetObjectProperties(object objectToReset, object parent, string elementName)
        {
            if (objectToReset != null)
            {
                IList list = objectToReset as IList;
                if ((list != null) && this.IsSerializableContent(elementName, parent))
                {
                    list.Clear();
                }
                else
                {
                    PropertyInfo[] properties = objectToReset.GetType().GetProperties();
                    if (properties != null)
                    {
                        foreach (PropertyInfo info in properties)
                        {
                            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(objectToReset)[info.Name];
                            if (descriptor != null)
                            {
                                SerializationVisibilityAttribute attribute = (SerializationVisibilityAttribute) descriptor.Attributes[typeof(SerializationVisibilityAttribute)];
                                if ((attribute != null) && (attribute.Visibility == SerializationVisibility.Hidden))
                                {
                                    goto Label_026E;
                                }
                            }
                            bool flag = this.IsSerializableContent(info.Name, objectToReset);
                            if (!this.IsChartBaseProperty(objectToReset, parent, info))
                            {
                                if (info.CanRead && (info.PropertyType.GetInterface("IList", true) != null))
                                {
                                    if (flag)
                                    {
                                        bool flag2 = false;
                                        MethodInfo method = objectToReset.GetType().GetMethod("Reset" + info.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                                        if (method != null)
                                        {
                                            method.Invoke(objectToReset, null);
                                            flag2 = true;
                                        }
                                        if (!flag2)
                                        {
                                            ((IList) info.GetValue(objectToReset, null)).Clear();
                                        }
                                    }
                                    else
                                    {
                                        foreach (object obj2 in (IList) info.GetValue(objectToReset, null))
                                        {
                                            this.ResetObjectProperties(obj2, objectToReset, this.GetObjectName(obj2));
                                        }
                                    }
                                }
                                else if ((info.CanRead && info.CanWrite) && ((info.Name != "Item") && (info.Name != "Name")))
                                {
                                    if (this.ShouldSerializeAsAttribute(info, objectToReset))
                                    {
                                        if (flag && (descriptor != null))
                                        {
                                            object obj3 = info.GetValue(objectToReset, null);
                                            DefaultValueAttribute attribute2 = (DefaultValueAttribute) descriptor.Attributes[typeof(DefaultValueAttribute)];
                                            if (attribute2 != null)
                                            {
                                                if (obj3 == null)
                                                {
                                                    if (attribute2.Value != null)
                                                    {
                                                        descriptor.SetValue(objectToReset, attribute2.Value);
                                                    }
                                                }
                                                else if (!obj3.Equals(attribute2.Value))
                                                {
                                                    descriptor.SetValue(objectToReset, attribute2.Value);
                                                }
                                            }
                                            else
                                            {
                                                MethodInfo info3 = objectToReset.GetType().GetMethod("Reset" + info.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
                                                if (info3 != null)
                                                {
                                                    info3.Invoke(objectToReset, null);
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        this.ResetObjectProperties(info.GetValue(objectToReset, null), objectToReset, info.Name);
                                    }
                                }
                            }
                        Label_026E:;
                        }
                    }
                }
            }
        }

        internal abstract void Serialize(object objectToSerialize, object destination);
        internal bool SerializeICollAsAtribute(PropertyInfo pi, object objectToSerialize)
        {
            if (objectToSerialize != null)
            {
                PropertyDescriptor descriptor = TypeDescriptor.GetProperties(objectToSerialize)[pi.Name];
                if (descriptor != null)
                {
                    SerializationVisibilityAttribute attribute = (SerializationVisibilityAttribute) descriptor.Attributes[typeof(SerializationVisibilityAttribute)];
                    if ((attribute != null) && (attribute.Visibility == SerializationVisibility.Attribute))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        internal bool ShouldSerializeAsAttribute(PropertyInfo pi, object parent)
        {
            if (parent != null)
            {
                PropertyDescriptor descriptor = TypeDescriptor.GetProperties(parent)[pi.Name];
                if (descriptor != null)
                {
                    SerializationVisibilityAttribute attribute = (SerializationVisibilityAttribute) descriptor.Attributes[typeof(SerializationVisibilityAttribute)];
                    if (attribute != null)
                    {
                        if (attribute.Visibility == SerializationVisibility.Attribute)
                        {
                            return true;
                        }
                        if (attribute.Visibility == SerializationVisibility.Element)
                        {
                            return false;
                        }
                    }
                }
            }
            if (pi.PropertyType.IsClass && (((pi.PropertyType != typeof(string)) && (pi.PropertyType != typeof(Font))) && ((pi.PropertyType != typeof(Color)) && (pi.PropertyType != typeof(Image)))))
            {
                return false;
            }
            return true;
        }

        internal bool IsResetWhenLoading
        {
            get
            {
                return this._isResetWhenLoading;
            }
            set
            {
                this._isResetWhenLoading = value;
            }
        }

        internal bool IsTemplateMode
        {
            get
            {
                return this._isTemplateMode;
            }
            set
            {
                this._isTemplateMode = value;
            }
        }

        internal bool IsUnknownAttributeIgnored
        {
            get
            {
                return this._isUnknownAttributeIgnored;
            }
            set
            {
                this._isUnknownAttributeIgnored = value;
            }
        }

        internal string NonSerializableContent
        {
            get
            {
                return this._nonSerializableContent;
            }
            set
            {
                this._nonSerializableContent = value;
                this.nonSerializableContentList = null;
            }
        }

        internal string SerializableContent
        {
            get
            {
                return this._serializableContent;
            }
            set
            {
                this._serializableContent = value;
                this.serializableContentList = null;
            }
        }

        private class ItemInfo
        {
            public bool any;
            public bool endsWith;
            public string name = "";
            public bool startsWith;
        }
    }
}

